# !/usr/bin/env python
# encoding: utf-8


"""
  @author: gaogao
  @file: InstGenSMU_U2722A.py
  @time: 2022/2/23 15:01
  @desc:
"""
from traceback import print_last
from ATS.instrumentDriver import InstGen


class InstGenSMU_U2722A(InstGen.SMU):
    def __init__(self, name):
        super().__init__(name)

    def idn(self):
        return self.handler.ask("*IDN?")

    def set_voltage_range(self, channel: int, voltage_range: str):
        """
        设置2722的指定channel电压范围
        :param voltage_range:只有2V和20V两个值
        :param channel:
        :return:
        """
        self.handler.write(f"VOLTage:RANGe R{voltage_range}, (@{channel})")

    def close_all_channel(self, channel):
        self.handler.write(f"OUTPut 0, (@{channel})")

    def set_current_range_limit(self, current_range: str, current_limit: float, channel: int):
        """
        设置2722的指定channel的电流范围和保护电流,电流的range只有以下六种
        :param current_range:– R1uA – 1 μA range
                                – R10uA – 10 μA range
                                – R100uA – 100 μA range
                                – R1mA – 1 mA range
                                – R10mA – 10 mA range
                                – R120mA – 120 mA range
        :param limit:
        :param channel:
        :return:
        """
        self.handler.write(f"CURRent:RANGe R{current_range}, (@{channel})")
        self.handler.write(f"CURR:LIM {current_limit}, (@{channel})")
        # self.__link_range_compliance(current_range, limit, channel)

    def __link_range_compliance(self, i_range: str, i_limit: float, channel: int):
        # 2722A设置limit和range的关系
        # 当limit>=range,limit使用range，反之使用limit值
        i_range_dict = {"1uA": 1e-6, "10uA": 1e-5, "100uA": 1e-4, "1mA": 1e-3, "10mA": 1e-2, "120mA": 0.12}
        if i_range and i_limit:
            self.handler.write(f"CURRent:RANGe R{i_range}, (@{channel})")
            if float(i_range_dict[i_range]) >= float(i_limit):
                self.handler.write(f"CURR:LIM {i_range}, (@{channel})")
            else:
                self.handler.write(f"CURR:LIM {i_limit}, (@{channel})")

    def set_current_nplc(self, plc: int, channel: int):
        """
        This command sets the number of power line cycles taken for the current
        measurement. The value is coupled to APERture by the equation:
        APERture = NPLCycles/selected line frequency.
        设置2722指定channel的电流的积分时间
        :param plc: 0 to 255
        :param channel:1 to 3
        :return:
        """
        self.handler.write(f"SENS:CURR:NPLC {plc}, (@{channel})")

    def output_state(self, state: int, channel: int):
        """
        This enables or disables the output of the given channel(s).
        :param state: 0：Disable the output;1 enable the output
        :param channel: 1 through 3
        :return:
        """
        #
        self.handler.write(f"OUTPut {state}, (@{channel})")

    def init(self, channel=1):
        """
        初始化觸發系統
        :param channel:
        :return:
        """
        self.handler.write(f"INIT:TRAN (@{channel})")

    # 設置電壓
    def set_voltage(self, voltage: float, channel: int):
        """
        设置指定channel的电压
        :param voltage:
        :param channel:
        :return:
        """
        cmd = f"VOLT {voltage}, (@{channel})"
        print("cmd", cmd)
        self.handler.write(cmd)
        print("after")

    #
    def set_current(self, current: float, v_compliance: float, channel: int):
        """
        設置指定channel的電流和保护电压
        :param current:
        :param v_compliance:
        :param channel:
        :return:
        """
        cmds = [f"CURR {current}, (@{channel})", f"VOLT:LIM {v_compliance}, (@{channel})"]
        for cmd in cmds:
            self.handler.write(cmd)

    #
    def measure_voltage(self, channel: int):
        """
        測量指定channel的電壓
        :param channel:
        :return:
        """
        cmd = f"MEAS:VOLT? (@{channel})"
        return self.handler.ask(cmd)

    #
    def measure_current(self, channel: int):
        """
        測量指定channel的電流
        :param channel:
        :return:
        """
        cmd = f"MEAS:CURR? (@{channel})"
        print(cmd)
        return self.handler.ask(cmd)

    # 设置点数
    def set_sweep_points(self, points: int, channel: int):
        """
        :param channel:1:3
        :param points:1:4096
        :return:
        """
        cmd = f"SENSe:SWEep:POINts {points}, (@{channel})"
        self.handler.write(cmd)

    # 查询设置的点数
    def query_sweep_points(self, channel: int):
        cmd = f"SENSe:SWEep:POINts? (@{channel})"
        return self.handler.ask(cmd)

    @DeprecationWarning
    def measure_array_current(self, channel: int):
        cmd = f"MEASure:ARRay:CURRent? (@{channel})"
        return self.handler.ask(cmd)

    @DeprecationWarning
    def measure_array_voltage(self, channel: int):
        cmd = f"MEASure:ARRay:VOLTage? (@{channel})"
        return self.handler.ask(cmd)

    def trigger(self, tag="NONE"):
        """
        :param tag:NONE or STRG
        :return:
        """
        cmd = f"TRIGger:SOURce {tag}"
        self.handler.write(cmd)

    def __reset(self):
        self.handler.write("*RST")
